
/****************************** ͷ�ļ� *****************************/
#include "mcu_self_diag.h"
#include "mcu_self_api.h"



/*
	0 0000 0000 0000
	0 0000 0000 0001 1			-	01 
	0 0000 0000 0010 2			-	02 
	0 0000 0000 0100 4			-	04
	0 0000 0000 1000 8			-	08
	0 0000 0001 0000 16			-	10
	0 0000 0010 0000 32			-	20	
	0 0000 0100 0000 62			-	40
	0 0000 1000 0000 128		-	80
	0 0001 0000 0000 256		-	100
	0 0010 0000 0000 512		-	200
	0 0100 0000 0000 1024 	-	400
	0 1000 0000 0000 2048		-	800	
	1 0000 0000 0000 4096		-	1000
*/
/** 地址总线 */
const static uint32_t InterBusAddress[] = {
	0x20000000,
	0x20000001,
	0x20000002,
	0x20000004,
	0x20000008,
	0x20000010,
	0x20000020,
	0x20000040,
	0x20000080,
	0x20000100,
	0x20000200,
	0x20000400,
	0x20000800,
	0x20001000,
};
	
/* 测试数据 */
const uint32_t InterBusTestData[] = {
	0x000000A5U,
	0x0000005AU,
	0x0000C300U,
	0x00003C00U,
	0x000F0000U,
	0x00F00000U,
	0xEC000000U,
	0x13000000U,
	0x00AA0000U,
	0x00550000U,
	0x00003300U,
	0x0000CC00U,
	0x000000A8U,
	0x00000054U,
};

/****************************** ��������***************************/
/*��ջ���ʹ������*/

static const uint32_t DIAG_STACK_DAT[8] = {0x00000000U, 0x55aa55aaU, 0x55555555U, 0x5a5a5a5aU, 
					   0xFFFFFFFFU, 0x33cc33ccU, 0xAAAAAAAAu, 0xc3c3c3c3U, 
					   };

					   
/* March test u32_data */
const uint32_t	U32_MARCH_DB[8]		= {0x00000000u, 0x55555555u, 0x33333333u, 0x0F0F0F0Fu,
					   0x00FF00FFu, 0xFF00FF00u, 0x0000FFFFu, 0xFFFF0000u};
const uint32_t	U32_MARCH_DB_BAR[8] = {0xFFFFFFFFu, 0xAAAAAAAAu, 0xCCCCCCCCu, 0xF0F0F0F0u,
					   0xFF00FF00u, 0x00FF00FFu, 0xFFFF0000u, 0x0000FFFFu};
				
uint32_t *pRunCrc32Chk           			__attribute__((section("CHENZHU_SIL_RAM")));
uint32_t *pRunCrc32ChkInv        			__attribute__((section("CHENZHU_SIL_RAM_REV")));
	   
void FlashCrc32_Init(void);
					   
static volatile uint32_t u32a_stack_top[8u] __attribute__((section("STACK_TOP"), zero_init));
static volatile uint32_t u32a_stack_bot[8u] __attribute__((section("STACK_BOT"), zero_init));

static uint32_t	g_u32_flash_crc	= 0xFFFFFFFFu;

static uint8_t u8ga_mcu_fault_rcd[FAULT_IDX_MAX] = {0u};
static bool_t b8gv_fault_alarm	= BFALSE;
static bool_t b8gv_fault_exec	= BFALSE;

static uint8_t	u8gv_seq_logic_cnt	= 0u;
static uint8_t	g_u8_fault_cfrm_num	= 0u;
static uint8_t	g_u8_run_mode		= 0u;
fun_wd_clr		g_fp_wd_clr			= 0u;
fun_diag_sfr	g_fp_diag_sfr_rcc		= 0u;
fun_diag_sfr	g_fp_diag_sfr_syscfg	= 0u;
fun_diag_sfr	g_fp_diag_sfr_exti		= 0u;

/****************************** ������ ***************************/
void diag_mcu_init(uint8_t u8_run_mode, uint8_t u8_fault_tol_num, \
					fun_wd_clr fp_wd_clr)
{
	uint8_t		u8lv_i = 0u;
	
	g_u8_run_mode		= u8_run_mode;
	g_u8_fault_cfrm_num	= (uint8_t)(u8_fault_tol_num << 2u);
	g_fp_wd_clr			= fp_wd_clr;
	
	/* RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE); */
	RCC->AHBENR |= SF_RCC_AHBENR_CRCEN;
	/* CRC_DeInit(); */
	/* DeInit CRC module */
	/* Set DR register to reset value */
	CRC->DR = 0xFFFFFFFFu;
	/* Reset IDR register */
	CRC->IDR = 0x00u;
	/* Set INIT register to reset value */
	CRC->INIT = 0xFFFFFFFFu;
	/* Reset the CRC calculation unit */
	CRC->CR = SF_CRC_CR_RESET;

	/* Init stack space */
	diag_init_stack();

	RCC->CSR = 0x01000000u;
	/*
	if((u32lv_rst_reg & 0xF2000000u) == 0u) {
		RCC->CSR = u32lv_rst_reg | 0x01000000u;
	} else {
		;
	}
	*/

	g_u32_flash_crc	= 0xFFFFFFFFu;
	
	for(u8lv_i = 0u; u8lv_i < FAULT_IDX_MAX; u8lv_i ++) {
		u8ga_mcu_fault_rcd[u8lv_i] = 0u;
	}
	b8gv_fault_alarm  = BFALSE;
	b8gv_fault_exec	  = BFALSE;

	u8gv_seq_logic_cnt	= 0u;
}

void diag_mcu_set_sfr_fun(fun_diag_sfr diag_sfr_rcc, fun_diag_sfr diag_sfr_syscfg, fun_diag_sfr diag_sfr_exti)
{
	g_fp_diag_sfr_rcc		= diag_sfr_rcc;
	g_fp_diag_sfr_syscfg	= diag_sfr_syscfg;
	g_fp_diag_sfr_exti		= diag_sfr_exti;
}

static bool_t diag_rst_circuitry(void)
{
	bool_t	b8lv_fail	= BFALSE;

	uint32_t u32lv_rst_reg	= 0u;
	u32lv_rst_reg = RCC->CSR;

	if((u32lv_rst_reg & 0xFE000000u) != 0u){
		b8lv_fail = BTRUE;
		(void)diag_set_fault(FAULT_IDX_RST);
	} else {
		b8lv_fail = BFALSE;
		(void)diag_reco_fault(FAULT_IDX_RST);
	}

	return b8lv_fail;
}

bool_t diag_mcu_po(void)
{
	uint16_t	u16_diag_step = 0u;
	bool_t		b8_fail	= BFALSE;

	__disable_irq();
	
	b8_fail = diag_rst_circuitry();
	
	for(u16_diag_step = 0; u16_diag_step < DIAG_STEP_FR; u16_diag_step ++){
		b8_fail = diag_flg_reg(u16_diag_step);
	}
	
	for(u16_diag_step = 0; u16_diag_step < DIAG_STEP_STACK; u16_diag_step ++){
		b8_fail = diag_cycle_stack(u16_diag_step);
	}
	
	for(u16_diag_step = 0; u16_diag_step < DIAG_STEP_CRC; u16_diag_step ++){
		b8_fail = diag_hardware_crc(u16_diag_step);
	}
	
	for(u16_diag_step = 0; u16_diag_step < DIAG_STEP_INT; u16_diag_step ++){
		b8_fail = diag_interrupt(u16_diag_step);
	}
	
	for(u16_diag_step = 0; u16_diag_step < DIAG_STEP_SP; u16_diag_step ++){
		b8_fail = diag_stack_pointer(u16_diag_step);
	}
	
	for(u16_diag_step = 0; u16_diag_step < DIAG_STEP_ISTR; u16_diag_step ++){
		b8_fail = diag_istr_set(u16_diag_step);
	}
	
	for(u16_diag_step = 0; u16_diag_step < DIAG_STEP_GPR; u16_diag_step ++){
		b8_fail = diag_gpr_reg(u16_diag_step);
	}
	
	if(g_u8_run_mode == RUN_MODE_DBG){
		b8_fail = BFALSE;
	}else{
		for(u16_diag_step = 0; u16_diag_step < DIAG_STEP_FLASH; u16_diag_step ++){
			b8_fail = diag_flash(u16_diag_step);
		}
	}
	
	for(u16_diag_step = 0; u16_diag_step < DIAG_STEP_SRAM; u16_diag_step ++){
		b8_fail = diag_sram(u16_diag_step);
	}

	__enable_irq();

	for(u16_diag_step = 0; u16_diag_step < FAULT_IDX_MAX; u16_diag_step ++){
		if(u8ga_mcu_fault_rcd[u16_diag_step] != 0u){
			b8gv_fault_alarm	= BTRUE;
			b8gv_fault_exec		= BTRUE;
		}else{
			;
		}
	}

	return b8_fail;
}


bool_t diag_mcu_cycle(const uint8_t u8lc_init_val, const uint8_t u8lc_incr_val)
{
	static uint16_t u16gv_diag_step = 0u;
	uint16_t	u16lv_tmp_step = 0u;

	bool_t	b8lv_fail	= BFALSE;

	diag_rcd_run_logic(u8lc_init_val, u8lc_incr_val);

	u16gv_diag_step ++ ;
	
	__disable_irq();
	
	if(u16gv_diag_step < DIAG_ST_STEP_FR) {
		/* u16lv_tmp_step = u16gv_diag_step - DIAG_ST_STEP_RST; */
		b8lv_fail = diag_rst_circuitry();
	} else if(u16gv_diag_step < DIAG_ST_STEP_STACK) {
		u16lv_tmp_step = u16gv_diag_step - DIAG_ST_STEP_FR;
		b8lv_fail = diag_flg_reg(u16lv_tmp_step);
	} else if(u16gv_diag_step < DIAG_ST_STEP_CRC) {
		u16lv_tmp_step = u16gv_diag_step - DIAG_ST_STEP_STACK;
		b8lv_fail = diag_cycle_stack(u16lv_tmp_step);
	} else if(u16gv_diag_step < DIAG_ST_STEP_INT) {
		u16lv_tmp_step = u16gv_diag_step - DIAG_ST_STEP_CRC;
		b8lv_fail = diag_hardware_crc(u16lv_tmp_step);
	} else if(u16gv_diag_step < DIAG_ST_STEP_SP) {
		u16lv_tmp_step = u16gv_diag_step - DIAG_ST_STEP_INT;
		b8lv_fail = diag_interrupt(u16lv_tmp_step);
	} else if(u16gv_diag_step < DIAG_ST_STEP_ISTR) {
		u16lv_tmp_step = u16gv_diag_step - DIAG_ST_STEP_SP;
		b8lv_fail = diag_stack_pointer(u16lv_tmp_step);
	} else if(u16gv_diag_step < DIAG_ST_STEP_GPR) {
		u16lv_tmp_step = u16gv_diag_step - DIAG_ST_STEP_ISTR;
		b8lv_fail = diag_istr_set(u16lv_tmp_step);
	} else if(u16gv_diag_step < DIAG_ST_STEP_FLASH) {
		u16lv_tmp_step = u16gv_diag_step - DIAG_ST_STEP_GPR;
		b8lv_fail = diag_gpr_reg(u16lv_tmp_step);
	} else if(u16gv_diag_step < DIAG_ST_STEP_SRAM) {
		if(g_u8_run_mode == RUN_MODE_DBG){
			b8lv_fail = BFALSE;
		}else{
			u16lv_tmp_step = u16gv_diag_step - DIAG_ST_STEP_FLASH;
			b8lv_fail = diag_flash(u16lv_tmp_step);
		}
	} else if(u16gv_diag_step < DIAG_ST_STEP_SFR) {
		u16lv_tmp_step = u16gv_diag_step - DIAG_ST_STEP_SRAM;
		b8lv_fail = diag_sram(u16lv_tmp_step);
	} else if(u16gv_diag_step < DIAG_ST_STEP_LAST) {
		if(g_u8_run_mode == RUN_MODE_DBG){
			b8lv_fail = BFALSE;
		}else{
			u16lv_tmp_step = u16gv_diag_step - DIAG_ST_STEP_SFR;
			b8lv_fail = diag_sfr(u16lv_tmp_step);
		}
	} else {
		u16gv_diag_step = 0u;
	}
	
	__enable_irq();

	diag_fault_flg_verf();

	if(b8lv_fail == BTRUE) {
		DBG_PRINTF_MCU_DIAG("Step:%x,%d\n", b8lv_fail, u16gv_diag_step);
	} else {
		;
	}

	return b8lv_fail;
}


/*
名称：WalkingBitTest
功能：检测数据总线和地址总线是否正常
输入：无

返回值：无

作者：zjq - 2019.11.19
注意事项：
			1.RAM地址4字节对齐，地址操作时注意地址位置
			2.因为前连根地址线无法使用32位地址操作，所以采用8位地址操作的方式
---------------------------------------------
修改记录：
*/

static bool_t diag_sram(uint16_t u16_step)
{
//	uint16_t	u16lv_i		= 0u;
	bool_t	b8lv_fail	= BFALSE;

	uint8_t i = 0;

	uint32_t RamDataBuff[14] = {0};
	/* stm32f030c6 SRAM 4K 0x20000000 ~ 0x20000FFF*/
	/* 备份数据 */
	RamDataBuff[0] = *((uint8_t *)InterBusAddress[0]);
	RamDataBuff[1] = *((uint8_t *)InterBusAddress[1]);  
	RamDataBuff[2] = *((uint8_t *)InterBusAddress[2]); /* 地址线01 02 因地址位置不符合4字节对齐所以采用8位操作 */
	for(i=3;i<13;i++)
	{
		RamDataBuff[i] = *((uint32_t *)InterBusAddress[i]);
	}
	
	/* 写入测试数据 */
	*((uint8_t *)InterBusAddress[0]) = (uint8_t)InterBusTestData[0];
	*((uint8_t *)InterBusAddress[1]) = (uint8_t)InterBusTestData[1];
	*((uint8_t *)InterBusAddress[2]) = (uint8_t)InterBusTestData[2];
	for(i=3;i<13;i++)  
	{
		*((uint32_t *)InterBusAddress[i]) = InterBusTestData[i];
	}
	
	/* 读取测试数据 还原备份数据 */
	for(i=0; i<3; i++)
	{
		
		if((uint8_t)InterBusTestData[i] != *((uint8_t *)InterBusAddress[i]))
		{
			b8lv_fail	= BTRUE;
			break;
		}
	}
	if(b8lv_fail != BFALSE)
	{		
		for(i=3;i<13;i++) 
		{
			if(InterBusTestData[i] != *((uint32_t *)InterBusAddress[i]))
			{
				b8lv_fail	= BTRUE;
				break;
			}
		}
	}
	
	/* 还原备份数据 */
	*((uint8_t *)InterBusAddress[0]) = (uint8_t )RamDataBuff[0]; 		/* 数据还原 */
	*((uint8_t *)InterBusAddress[1]) = (uint8_t )RamDataBuff[1]; 		/* 数据还原 */
	*((uint8_t *)InterBusAddress[2]) = (uint8_t )RamDataBuff[2]; 		/* 数据还原 */
	for(i=3;i<13;i++) 
	{
		*((uint32_t *)InterBusAddress[i]) = (uint32_t )RamDataBuff[i]; /* 备份数据还原 */
	}
	
	if(b8lv_fail == BTRUE){
		(void)diag_set_fault(FAULT_IDX_SRAM);
	}else{
		(void)diag_reco_fault(FAULT_IDX_SRAM);
	}
	
	return b8lv_fail;
}

uint32_t diag_calc_crc32(uint32_t u32_crc_init_value, const uint8_t u8p_dat[], uint16_t u16_size )
{
	uint16_t u16lv_index = 0u;
	CRC->CR = SF_CRC_CR_RESET;	/* ��λCRC */
	CRC->INIT	= u32_crc_init_value;
	for( u16lv_index = 0u; u16lv_index < u16_size; u16lv_index++ ){
		CRC->DR = (uint32_t) u8p_dat[ u16lv_index ];
	}
	return ( CRC->DR );
}

#if 0
static uint32_t diag_calc_crc32_soft(uint32_t u32_crc_init_value, uint8_t *u8p_data, uint16_t u16_len )
{
	const uint32_t u32a_crc32_table[ 256u ] =
	{
		0x00000000u, 0x04C11DB7u, 0x09823B6Eu, 0x0D4326D9u, 0x130476DCu, 0x17C56B6Bu,
		0x1A864DB2u, 0x1E475005u, 0x2608EDB8u, 0x22C9F00Fu, 0x2F8AD6D6u, 0x2B4BCB61u,
		0x350C9B64u, 0x31CD86D3u, 0x3C8EA00Au, 0x384FBDBDu, 0x4C11DB70u, 0x48D0C6C7u,
		0x4593E01Eu, 0x4152FDA9u, 0x5F15ADACu, 0x5BD4B01Bu, 0x569796C2u, 0x52568B75u,
		0x6A1936C8u, 0x6ED82B7Fu, 0x639B0DA6u, 0x675A1011u, 0x791D4014u, 0x7DDC5DA3u,
		0x709F7B7Au, 0x745E66CDu, 0x9823B6E0u, 0x9CE2AB57u, 0x91A18D8Eu, 0x95609039u,
		0x8B27C03Cu, 0x8FE6DD8Bu, 0x82A5FB52u, 0x8664E6E5u, 0xBE2B5B58u, 0xBAEA46EFu,
		0xB7A96036u, 0xB3687D81u, 0xAD2F2D84u, 0xA9EE3033u, 0xA4AD16EAu, 0xA06C0B5Du,
		0xD4326D90u, 0xD0F37027u, 0xDDB056FEu, 0xD9714B49u, 0xC7361B4Cu, 0xC3F706FBu,
		0xCEB42022u, 0xCA753D95u, 0xF23A8028u, 0xF6FB9D9Fu, 0xFBB8BB46u, 0xFF79A6F1u,
		0xE13EF6F4u, 0xE5FFEB43u, 0xE8BCCD9Au, 0xEC7DD02Du, 0x34867077u, 0x30476DC0u,
		0x3D044B19u, 0x39C556AEu, 0x278206ABu, 0x23431B1Cu, 0x2E003DC5u, 0x2AC12072u,
		0x128E9DCFu, 0x164F8078u, 0x1B0CA6A1u, 0x1FCDBB16u, 0x018AEB13u, 0x054BF6A4u,
		0x0808D07Du, 0x0CC9CDCAu, 0x7897AB07u, 0x7C56B6B0u, 0x71159069u, 0x75D48DDEu,
		0x6B93DDDBu, 0x6F52C06Cu, 0x6211E6B5u, 0x66D0FB02u, 0x5E9F46BFu, 0x5A5E5B08u,
		0x571D7DD1u, 0x53DC6066u, 0x4D9B3063u, 0x495A2DD4u, 0x44190B0Du, 0x40D816BAu,
		0xACA5C697u, 0xA864DB20u, 0xA527FDF9u, 0xA1E6E04Eu, 0xBFA1B04Bu, 0xBB60ADFCu,
		0xB6238B25u, 0xB2E29692u, 0x8AAD2B2Fu, 0x8E6C3698u, 0x832F1041u, 0x87EE0DF6u,
		0x99A95DF3u, 0x9D684044u, 0x902B669Du, 0x94EA7B2Au, 0xE0B41DE7u, 0xE4750050u,
		0xE9362689u, 0xEDF73B3Eu, 0xF3B06B3Bu, 0xF771768Cu, 0xFA325055u, 0xFEF34DE2u,
		0xC6BCF05Fu, 0xC27DEDE8u, 0xCF3ECB31u, 0xCBFFD686u, 0xD5B88683u, 0xD1799B34u,
		0xDC3ABDEDu, 0xD8FBA05Au, 0x690CE0EEu, 0x6DCDFD59u, 0x608EDB80u, 0x644FC637u,
		0x7A089632u, 0x7EC98B85u, 0x738AAD5Cu, 0x774BB0EBu, 0x4F040D56u, 0x4BC510E1u,
		0x46863638u, 0x42472B8Fu, 0x5C007B8Au, 0x58C1663Du, 0x558240E4u, 0x51435D53u,
		0x251D3B9Eu, 0x21DC2629u, 0x2C9F00F0u, 0x285E1D47u, 0x36194D42u, 0x32D850F5u,
		0x3F9B762Cu, 0x3B5A6B9Bu, 0x0315D626u, 0x07D4CB91u, 0x0A97ED48u, 0x0E56F0FFu,
		0x1011A0FAu, 0x14D0BD4Du, 0x19939B94u, 0x1D528623u, 0xF12F560Eu, 0xF5EE4BB9u,
		0xF8AD6D60u, 0xFC6C70D7u, 0xE22B20D2u, 0xE6EA3D65u, 0xEBA91BBCu, 0xEF68060Bu,
		0xD727BBB6u, 0xD3E6A601u, 0xDEA580D8u, 0xDA649D6Fu, 0xC423CD6Au, 0xC0E2D0DDu,
		0xCDA1F604u, 0xC960EBB3u, 0xBD3E8D7Eu, 0xB9FF90C9u, 0xB4BCB610u, 0xB07DABA7u,
		0xAE3AFBA2u, 0xAAFBE615u, 0xA7B8C0CCu, 0xA379DD7Bu, 0x9B3660C6u, 0x9FF77D71u,
		0x92B45BA8u, 0x9675461Fu, 0x8832161Au, 0x8CF30BADu, 0x81B02D74u, 0x857130C3u,
		0x5D8A9099u, 0x594B8D2Eu, 0x5408ABF7u, 0x50C9B640u, 0x4E8EE645u, 0x4A4FFBF2u,
		0x470CDD2Bu, 0x43CDC09Cu, 0x7B827D21u, 0x7F436096u, 0x7200464Fu, 0x76C15BF8u,
		0x68860BFDu, 0x6C47164Au, 0x61043093u, 0x65C52D24u, 0x119B4BE9u, 0x155A565Eu,
		0x18197087u, 0x1CD86D30u, 0x029F3D35u, 0x065E2082u, 0x0B1D065Bu, 0x0FDC1BECu,
		0x3793A651u, 0x3352BBE6u, 0x3E119D3Fu, 0x3AD08088u, 0x2497D08Du, 0x2056CD3Au,
		0x2D15EBE3u, 0x29D4F654u, 0xC5A92679u, 0xC1683BCEu, 0xCC2B1D17u, 0xC8EA00A0u,
		0xD6AD50A5u, 0xD26C4D12u, 0xDF2F6BCBu, 0xDBEE767Cu, 0xE3A1CBC1u, 0xE760D676u,
		0xEA23F0AFu, 0xEEE2ED18u, 0xF0A5BD1Du, 0xF464A0AAu, 0xF9278673u, 0xFDE69BC4u,
		0x89B8FD09u, 0x8D79E0BEu, 0x803AC667u, 0x84FBDBD0u, 0x9ABC8BD5u, 0x9E7D9662u,
		0x933EB0BBu, 0x97FFAD0Cu, 0xAFB010B1u, 0xAB710D06u, 0xA6322BDFu, 0xA2F33668u,
		0xBCB4666Du, 0xB8757BDAu, 0xB5365D03u, 0xB1F740B4u
	};
	uint32_t u32_crc_reg	= 0u;
	uint32_t u32_tmp		= 0u;
	uint16_t u16_i	= 0u;
	uint16_t u16_n	= 0u;

	u32_crc_reg = u32_crc_init_value;
	for ( u16_n = 0; u16_n < u16_len; u16_n++ ){
		u32_crc_reg ^= (uint32_t) u8p_data[ u16_n ];
		for ( u16_i = 0; u16_i < 4; u16_i++ ){
			u32_tmp = u32a_crc32_table[ ( uint8_t )( ( u32_crc_reg >> 24 ) & 0xff ) ]; /* 取一个字节，查表 */
			u32_crc_reg <<= 8; /* 丢掉计算过的头一个BYTE */
			u32_crc_reg ^= u32_tmp; /* 与前一个BYTE的计算结果异或 */
		}
	}
	return u32_crc_reg;
}
/* #else */
#define SOFT_CRC32_POLYNOMIAL	0x04C11DB7u
static uint32_t diag_calc_crc32_soft(uint32_t u32_crc_init_value, uint8_t u8p_data[], uint16_t u16_len )
{
	uint32_t u32_xbit		= 0x00000000u;
	uint32_t u32_data		= 0x00000000u;
	uint32_t u32_crc_reg	= 0xFFFFFFFF;	/* 初值 */
	uint32_t u32_bits		= 0x00000000u;
	uint32_t i;

	u32_crc_reg = u32_crc_init_value;

	for(i = 0;i < u16_len;i ++)
	{
		u32_xbit = 1u << 31u;
		u32_data = (uint32_t)u8p_data[i];
		u32_data = (uint32_t)(u32_data << 24u) | 0x00FFFFFFu;
		for(u32_bits = 0u; u32_bits < 32u; u32_bits++)
		{
			if (u32_crc_reg & 0x80000000u) {
			u32_crc_reg <<= 1u;
			u32_crc_reg ^= SOFT_CRC32_POLYNOMIAL;
			}  
			else  
			u32_crc_reg <<= 1u;
			if (u32_data & u32_xbit)
			u32_crc_reg ^= SOFT_CRC32_POLYNOMIAL;

			u32_xbit >>= 1u;
		}
	}
	return u32_crc_reg;
}
#endif

/*
名称:FlashCheck_PowerON()

功能:
FLASH上电检测函数，整片检查

作者:	ZhangJQ  -- 2019.11.15

输入:
输出: 0 -- FLASH内容有错误出现
	  1 -- FLASH内容无错误出现

返回值:无

使用注意:
上电之后调用，程序运行时不要调用
*/

uint8_t FlashCheck_PowerON(void)
{	
	uint32_t i,k;

	uint8_t ret=1;
	uint32_t* p;
	
	
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC,ENABLE);	

	for(k=0;k<NUM_OF_BLOCK;k++)
	{

		CRC_ResetDR();
		CRC_SetInitRegister(g_u32_flash_crc);
		CRC_ReverseInputDataSelect(CRC_ReverseInputData_No);
		CRC_ReverseOutputDataCmd(DISABLE);

		p=ROM_START+ROM_BLOCK_SIZE_InWord*k;
		for(i=0;i<ROM_BLOCK_SIZE_InWord;i++)
		{
			CRC->DR = *(p + i);
		}


		if(CRC->DR != *(uint32_t *)((&__Check_Sum)+k))
		{
			ret = 0;
			break;
		}
	}



	return (ret);
	
	
}

typedef enum 
{
	TEST_RUNNING,
	TEST_ERROR,
	TEST_SUCCESS,
}MyTestStatus;

/*
名称:FlashCheck_RunTime()

功能:
FLASH运行检测函数，块检查

作者:	ZhangJQ  -- 2019.11.15

输入:
输出: 自诊断状态

返回值:无

使用注意:
*/
MyTestStatus FlashCheck_RunTime(void)
{
	MyTestStatus T_Status = TEST_RUNNING; 

	static uint8_t iBlock=0;
	if ((((uint32_t)pRunCrc32Chk) ^ ((uint32_t)pRunCrc32ChkInv)) == 0xFFFFFFFFuL)
	{
		uint8_t i=0;
		for(i=0;
			i<ROM_STEP_SIZE_InWords;
			i++)
		{
			CRC->DR = *pRunCrc32Chk;
			pRunCrc32Chk++;
			pRunCrc32ChkInv--;
		}
		if(pRunCrc32Chk<ROM_START+(iBlock+1)*ROM_BLOCK_SIZE_InWord)
		{
			T_Status = TEST_RUNNING;

		}
		else
		{
			if(CRC->DR != *(uint32_t *)((&__Check_Sum)+iBlock))
			{
				T_Status = TEST_ERROR;	
			}
			else
			{
				T_Status = TEST_SUCCESS;
				CRC_ResetDR();

			}
			
			if(iBlock==7)
			{
				FlashCrc32_Init();
				iBlock=0;
			}
			else
			{
				iBlock++;
			}

		}

	}
	else  /* Class B error pRunCrc32Chk */
	{
		T_Status = TEST_ERROR;		
	}

	return (T_Status);

}


void FlashCrc32_Init(void)
{
	
	pRunCrc32Chk = (uint32_t*)ROM_START;
	pRunCrc32ChkInv = ((uint32_t *)(uint32_t)(~(uint32_t)(ROM_START)));
	

	/** FLASH初始化 **/
	CRC_ResetDR();
	CRC_SetInitRegister(g_u32_flash_crc);
	CRC_ReverseInputDataSelect(CRC_ReverseInputData_No);
	CRC_ReverseOutputDataCmd(DISABLE);
}







static bool_t diag_flash(uint16_t u16_step)
{
	bool_t		b8lv_fail		= BFALSE;
	
	if(FlashCheck_RunTime() == TEST_ERROR)
	{
		b8lv_fail = BTRUE;
		(void)diag_set_fault(FAULT_IDX_FLASH);
		
	}
	else
	{
		b8lv_fail = BFALSE;
	}
	
	return b8lv_fail;
}

static bool_t diag_istr_set(uint16_t u16_step)
{
	bool_t	b8lv_fail	= BFALSE;
	uint16_t	u16lv_step	= u16_step;
	uint32_t	u32lv_dat_tmp	= 0u;
	
	static bool_t	b8gv_fault_cyc_istr	= BFALSE;
	
	switch(u16lv_step){
	case 0u :{
		u32lv_dat_tmp = _diag_istr_set_step1();
		break;
	}
	case 1u :{
		u32lv_dat_tmp = _diag_istr_set_step2();
		break;
	}
	case 2u :{
		u32lv_dat_tmp = _diag_istr_set_step3();
		break;
	}
	case 3u :{
		u32lv_dat_tmp = _diag_istr_set_step4();
		break;
	}
	case 4u :{
		u32lv_dat_tmp = _diag_istr_set_step5();
		break;
	}
	case 5u :{
		u32lv_dat_tmp = _diag_istr_set_step6();
		break;
	}
	case 6u :{
		u32lv_dat_tmp = _diag_istr_set_step7();
		break;
	}
	case 7u :{
		u32lv_dat_tmp = _diag_istr_set_step8();
		break;
	}
	case 8u:{
		if(b8gv_fault_cyc_istr == BFALSE){
			(void)diag_reco_fault(FAULT_IDX_ISTR);
		}else{
			b8gv_fault_cyc_istr = BFALSE;
		}
		break;
	}
	default : break;
	}

	if(u32lv_dat_tmp == 1u){
		b8lv_fail = BTRUE;
		b8gv_fault_cyc_istr = BTRUE;
		(void)diag_set_fault(FAULT_IDX_ISTR);
	}else{
		b8lv_fail = BFALSE;
	}
	
	return b8lv_fail;
}

static bool_t diag_flg_reg(uint16_t u16_step)
{
	bool_t	b8lv_fail	= BFALSE;
	uint32_t	u32lv_dat_tmp	= 0u;

	u32lv_dat_tmp = _diag_flg_reg();

	if(u32lv_dat_tmp == 1u) {
		b8lv_fail = BTRUE;
		(void)diag_set_fault(FAULT_IDX_FR);
	}else {
		b8lv_fail = BFALSE;
		(void)diag_reco_fault(FAULT_IDX_FR);
	}
	
	return b8lv_fail;
}

static bool_t diag_gpr_reg(uint16_t u16_step)
{
	uint32_t	u32lv_dat_tmp	= 0u;
	bool_t	b8lv_fail	= BFALSE;
	uint16_t	u16lv_step	= u16_step;
	
	static bool_t	b8gv_fault_cyc_gpr	= BFALSE;
	
	switch(u16lv_step){
	case 0u : {
		u32lv_dat_tmp = _diag_gpr_step1();
		break;
	}
	case 1u : {
		u32lv_dat_tmp = _diag_gpr_step2();
		break;
	}
	case 2u : {
		u32lv_dat_tmp = _diag_gpr_step3();
		break;
	}
	case 3u : {
		u32lv_dat_tmp = _diag_gpr_step4();
		break;
	}
	case 4u : {
		u32lv_dat_tmp = _diag_gpr_step5();
		break;
	}
	case 5u : {
		u32lv_dat_tmp = _diag_gpr_step6();
		break;
	}
	case 6u : {
		u32lv_dat_tmp = _diag_gpr_step7();
		break;
	}
	case 7u : {
		u32lv_dat_tmp = _diag_gpr_step8();
		break;
	}
	case 8u : {
		u32lv_dat_tmp = _diag_gpr_step9();
		break;
	}
	case 9u : {
		u32lv_dat_tmp = _diag_gpr_step10();
		break;
	}
	case 10u : {
		u32lv_dat_tmp = _diag_gpr_step11();
		break;
	}
	case 11u : {
		u32lv_dat_tmp = _diag_gpr_step12();
		break;
	}
	case 12u : {
		u32lv_dat_tmp = _diag_gpr_step13();
		break;
	}
	case 13u : {
		u32lv_dat_tmp = _diag_gpr_step14();
		break;
	}
	case 14u : {
		u32lv_dat_tmp = _diag_gpr_step15();
		break;
	}
	case 15u : {
		u32lv_dat_tmp = _diag_gpr_step16();
		break;
	}
	case 16u : {
		u32lv_dat_tmp = _diag_gpr_step17();
		break;
	}
	case 17u : {
		u32lv_dat_tmp = _diag_gpr_step18();
		break;
	}
	case 19u:{
		if (b8gv_fault_cyc_gpr == BFALSE) {
			(void)diag_reco_fault(FAULT_IDX_GPR);
		}
		else {
			b8gv_fault_cyc_gpr = BFALSE;
		}
		break;
	}
	default : break;
	}

	if(u32lv_dat_tmp == 1u){
		b8lv_fail = BTRUE;
		b8gv_fault_cyc_gpr = BTRUE;
		(void)diag_set_fault(FAULT_IDX_GPR);
	}else{
		b8lv_fail = BFALSE;
	}
	
	return b8lv_fail;
}

static bool_t diag_stack_pointer(uint16_t u16_step)
{
	bool_t	b8lv_fail	= BFALSE;
	uint32_t	u32lv_dat_tmp	= 0u;
	uint16_t	u16lv_step	= u16_step;
	
	static bool_t	b8gv_fault_cyc_sp	= BFALSE;
	
	switch(u16lv_step){
	case 0u :{
		u32lv_dat_tmp = _diag_psp_step1();
		break;
	}
	case 1u :{
		u32lv_dat_tmp = _diag_psp_step2();
		break;
	}
	case 2u :{
		u32lv_dat_tmp = _diag_msp_step1();
		break;
	}
	case 3u :{
		u32lv_dat_tmp = _diag_msp_step2();
		break;
	}
	case 4u:{
		if(b8gv_fault_cyc_sp == BFALSE){
			(void)diag_reco_fault(FAULT_IDX_SP);
		}else{
			b8gv_fault_cyc_sp = BFALSE;
		}
		break;
	}
	default :break;
	}
	
	if(u32lv_dat_tmp == 1u){
		b8lv_fail = BTRUE;
		b8gv_fault_cyc_sp = BTRUE;
		(void)diag_set_fault(FAULT_IDX_SP);
	}else{
		b8lv_fail = BFALSE;
	}

	return b8lv_fail;
}

static void diag_init_stack(void)
{
	uint16_t u16lv_i = 0u;

	for (u16lv_i = 0u; u16lv_i < 8U; u16lv_i++){
		u32a_stack_top[u16lv_i] = DIAG_STACK_DAT[u16lv_i];
		u32a_stack_bot[u16lv_i] = DIAG_STACK_DAT[u16lv_i];
	}
}

static bool_t diag_interrupt(uint16_t u16_step)
{
	bool_t	b8_fail	= BFALSE;
	
	if((EXTI->SWIER & 0x807AFFFFu) != 0x00000000u){
		b8_fail = BTRUE;
	}else{
		;
	}
	if((EXTI->PR & 0x807AFFFFu) != 0x00000000u){
		b8_fail = BTRUE;
	}else{
		;
	}
	if(b8_fail == BTRUE){
		(void)diag_set_fault(FAULT_IDX_INT);
	}else{
		(void)diag_reco_fault(FAULT_IDX_INT);
	}
	
	return b8_fail;
}


static bool_t diag_cycle_stack(uint16_t u16_step)
{
	bool_t	b8lv_fail	= BFALSE;
	uint16_t	u16lv_i		= 0u;

	for (u16lv_i = 0u; u16lv_i < 8U; u16lv_i++){
		if((u32a_stack_top[u16lv_i] != DIAG_STACK_DAT[u16lv_i])
		|| (u32a_stack_bot[u16lv_i] != DIAG_STACK_DAT[u16lv_i]))
		{
			b8lv_fail = BTRUE;
		}else{
			;
		}
	}
	
	if(b8lv_fail == BTRUE){
		(void)diag_set_fault(FAULT_IDX_STACK);
	}else{
		(void)diag_reco_fault(FAULT_IDX_STACK);
	}
	
	return b8lv_fail;
}

static bool_t diag_hardware_crc(uint16_t u16_step)
{
//	uint32_t u32lv_i = 0u;
	
	bool_t b8lv_fail = BFALSE;
	
	/* 此处CRC硬件不必在检测是有问题，FLASH检测时包含这一项
		2022.02.28 -ZhangJQ
	*/
//	CRC->CR		= (uint32_t)0x00000001u;
//	CRC->INIT	= 0xFFFFFFFFu;
//	for(u32lv_i = 0u; u32lv_i < 20u; u32lv_i ++){
//		CRC->DR = u32lv_i;
//	}
//	
//	if(CRC->DR != 0xB31F4E99u){
//		b8lv_fail = BTRUE;
//		(void)diag_set_fault(FAULT_IDX_CRC);
//	}else{
//		(void)diag_reco_fault(FAULT_IDX_CRC);
//	}
	
	return b8lv_fail;
}

static bool_t diag_sfr(uint16_t u16_step)
{
	bool_t b8_fail = BFALSE;
	static uint16_t s_b8_fault_cyc_sfr	= BFALSE;
	
	switch(u16_step){
	case 0u : {
		b8_fail = g_fp_diag_sfr_rcc();
		break;
	}
	case 1u : {
		b8_fail = g_fp_diag_sfr_syscfg();
		break;
	}
	case 2u : {
		b8_fail = g_fp_diag_sfr_exti();
		break;
	}
	case 3u : {
		if(s_b8_fault_cyc_sfr == BFALSE){
			(void)diag_reco_fault(FAULT_IDX_SFR);
		}else{
			s_b8_fault_cyc_sfr = BFALSE;
		}
		break;
	}
	default : break;
	}
	
	if(b8_fail == BTRUE){
		s_b8_fault_cyc_sfr = BTRUE;
		(void)diag_set_fault(FAULT_IDX_SFR);
	}else{
		;
	}
	
	return b8_fail;
}

//static bool_t diag_sfr_rcc(void)
//{
//	bool_t b8_fail = BFALSE;
//	
//	if((RCC->CR & 0x000C0001u) != 0x00000001u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((RCC->CFGR & 0xFF3F47F0u) != 0x001D0000u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((RCC->CIR & 0x00003F00u) != 0x00000000u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((RCC->AHBENR & 0x005E0055u) != 0x000E0055u){/* STO->0x000E0055u, SR->0x004E0055u   0x000E0055u -> 0x004E0055u*/
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((RCC->APB2ENR & 0x00475A21u) != 0x00020200u){/* STO->0x00020200u, SR->0x00025200u  0x00020200u -> 0x00025201u*/
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((RCC->APB1ENR & 0x10FE4932u) != 0x00000000u){/* STO->0x00000000u, SR->0x00000002u */
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((RCC->CSR & 0x00000001u) != 0x00000000u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((RCC->CFGR2 & 0x0000000Fu) != 0x00000004u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((RCC->CFGR3 & 0x00000093u) != 0x00000000u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((RCC->CR2 & 0x000000FDu) != 0x00000080u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	
//	return b8_fail;
//}

//static bool_t diag_sfr_syscfg(void)
//{
//	bool_t b8_fail = BFALSE;
//	
//	if((SYSCFG->CFGR1 & 0x04DF1F13u) != 0x00000000u){       //  0x00000000u -> 0x00000600u
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((SYSCFG->EXTICR[0] & 0x0000FFFFu) != 0x00000000u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((SYSCFG->EXTICR[1] & 0x0000FFFFu) != 0x00000000u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((SYSCFG->EXTICR[2] & 0x0000FFFFu) != 0x00000000u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((SYSCFG->EXTICR[3] & 0x0000FFFFu) != 0x00000000u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((SYSCFG->CFGR2 & 0x00000001u) != 0x00000000u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	
//	return b8_fail;
//}

//static bool_t diag_sfr_exti(void)
//{
//	bool_t b8_fail = BFALSE;
//	
//	if(EXTI->IMR != 0x0FF40000u){     //  0x0FF40000u -> 0x0F940000u
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if(EXTI->EMR != 0x00000000u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((EXTI->RTSR & 0x807AFFFFu) != 0x00000000u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	if((EXTI->FTSR & 0x807AFFFFu) != 0x00000000u){
//		b8_fail = BTRUE;
//	}else{
//		;
//	}
//	
//	return b8_fail;
//}

static uint16_t diag_set_fault(uint8_t u8_fault_idx)
{
	uint8_t u8lv_fault_idx = u8_fault_idx;
	if(u8ga_mcu_fault_rcd[u8lv_fault_idx] < FAULT_CNT_MAX) {
		u8ga_mcu_fault_rcd[u8lv_fault_idx] += 3u;
	} else {
		u8ga_mcu_fault_rcd[u8lv_fault_idx] = FAULT_CNT_MAX;
	}
	
	return (uint16_t)u8ga_mcu_fault_rcd[u8lv_fault_idx];
}

static uint16_t diag_reco_fault(uint8_t u8_fault_idx)
{
	uint8_t u8lv_fault_idx = u8_fault_idx;
	if(0u < u8ga_mcu_fault_rcd[u8lv_fault_idx]) {
		u8ga_mcu_fault_rcd[u8lv_fault_idx] -= 1u;
	} else {
		u8ga_mcu_fault_rcd[u8lv_fault_idx] = 0u;
	}
	
	return (uint16_t)u8ga_mcu_fault_rcd[u8lv_fault_idx];
}

static void diag_fault_flg_verf(void)
{
	uint8_t	u8lv_i		= 0u;

	bool_t	b8lv_fault_alarm_tmp	= BFALSE;
	bool_t	b8lv_fault_exec_tmp	= BFALSE;

	static uint8_t u8ga_mcu_fault_rcd_old[FAULT_IDX_MAX] = {0u};

	for(u8lv_i = 0u; u8lv_i < FAULT_IDX_MAX; u8lv_i ++) {
		if(g_u8_fault_cfrm_num < u8ga_mcu_fault_rcd[u8lv_i]) {
			b8lv_fault_exec_tmp		= BTRUE;
		} else if(0u < u8ga_mcu_fault_rcd[u8lv_i]) {
			b8lv_fault_alarm_tmp	= BTRUE;
		} else {
			;  /* Stay at current status */
		}
		
		if(u8ga_mcu_fault_rcd_old[u8lv_i] != u8ga_mcu_fault_rcd[u8lv_i]){
			u8ga_mcu_fault_rcd_old[u8lv_i] = u8ga_mcu_fault_rcd[u8lv_i];
			DBG_PRINTF_MCU_DIAG("MCU Err:%d\n", u8lv_i);
		} else {
			;
		}
	}
	
	if(b8lv_fault_exec_tmp == BTRUE) {
		b8gv_fault_exec = BTRUE;
	} else if(b8lv_fault_alarm_tmp == BFALSE) {
		b8gv_fault_exec = BFALSE;
	} else {
		; /* Stay at current status */
	}

	if(b8lv_fault_alarm_tmp == BTRUE) {
		b8gv_fault_alarm = BTRUE;
	} else {
		b8gv_fault_alarm = BFALSE;
	}
}

bool_t diag_get_fault_alarm(void)
{
	return b8gv_fault_alarm;
}

bool_t diag_get_fault_exec(void)
{
	return b8gv_fault_exec;
}

uint8_t diag_get_fault_cnt(uint8_t u8_fault_idx)
{
	uint8_t	u8_rtn_val	= 255u;
	if(u8_fault_idx < FAULT_IDX_MAX){
		u8_rtn_val = u8ga_mcu_fault_rcd[u8_fault_idx];
	} else{
		u8_rtn_val	= 255u;
	}
	return u8_rtn_val;
}

void diag_rcd_run_logic(const uint8_t u8lc_init_val, const uint8_t u8lc_incr_val)
{
	if (u8gv_seq_logic_cnt == u8lc_init_val) {
		u8gv_seq_logic_cnt += u8lc_incr_val;
	} else {
		;
	}
}

void diag_sequence_logic(const uint8_t u8lc_end_val)
{
	/* static uint8_t u8gv_clr_cnt	  = 0u; */
	
	if (u8gv_seq_logic_cnt == u8lc_end_val) {
		u8gv_seq_logic_cnt = 0u;
		
		/* MCU_CLR_WD(); */
		g_fp_wd_clr();
		
		if(0u < u8ga_mcu_fault_rcd[FAULT_IDX_SEQ_LOGIC]) {
			u8ga_mcu_fault_rcd[FAULT_IDX_SEQ_LOGIC] --;
		} else {
			u8ga_mcu_fault_rcd[FAULT_IDX_SEQ_LOGIC] = 0u;
		}
	} else {
		/* Run logic Err*/
		u8gv_seq_logic_cnt = 0u;
		
		if(g_u8_fault_cfrm_num < u8ga_mcu_fault_rcd[FAULT_IDX_SEQ_LOGIC]) {
			;
			/*
			while (1) {
				;
			}
			*/
		} else {
			u8ga_mcu_fault_rcd[FAULT_IDX_SEQ_LOGIC] ++;
		}
	}
}
